#include <QPluginLoader>
#include <QMessageBox>
#include <QMdiSubWindow>
#include <QFile>
#include <QMoveEvent>
#include <QFocusEvent>
#include <QResizeEvent>

#include <opencv/cv.h>
#include <opencv/highgui.h>

#include <iostream>

#include "QCVModuleInterface.h"
#include "QCVModuleHandlerInterface.h"

#ifndef QCVMODULELOADER_H
#define QCVMODULELOADER_H

/**
	@class QCVModuleHandler 
	@brief Permet le chargement et la gestion d'un module
*/

class QCVModuleHandler:public QMdiSubWindow,QCVModuleHandlerInterface 
{
  Q_OBJECT
  public:
		
		/**
		@param filename : Nom du module à charger
		@brief Charge un module
		*/
		QCVModuleHandler(QString filename);

		/**
		@brief Assure la destruction du module contenu
		*/    
		~QCVModuleHandler();
    
		/**
		@brief Force à émettre un signal de sortie, peut être utilisé par les modules
		*/
    void forceOutput(cv::Mat & m);
		
		/**
		@brief Retourne le nombre d'entrées du module chargé
		*/	    
		int getNbInputs();
		
		/**
		@brief Retourne le nom du module chargé
		*/	  
		QString getFilename();
		
		/**
		@brief Retourne l'aide du module chargé
		*/	      
		QString help(int id);
    
		/**
		@brief Retourne les parametres du module chargé
		*/
		QString getParams();

		/**
		@brief Affecte la configuration du module chargé
		*/
		bool setParams(QString params);
		
		/**
		@brief ajuste la taille du handler
		*/
		void adjust();
		
		bool isLoaded();
		
  public slots:
		/**
		@brief 
		Affecte l'entrée 0 du module chargé\n
		Si toutes les entrées sont chargé le module est exécuté (process()) et un signal est émit en sortie.		
		*/	
		void input0(cv::Mat & m);
		
		/**
		@brief 
		Affecte l'entrée 1 du module chargé\n
		Si toutes les entrées sont chargé le module est exécuté (process()) et un signal est émit en sortie.		
		*/	
		void input1(cv::Mat & m);
		
		/**
		@brief 
		Affecte l'entrée 2 du module chargé\n
		Si toutes les entrées sont chargé le module est exécuté (QCVModuleInterface::process()) et un signal est émit en sortie.		
		*/	    
		void input2(cv::Mat & m);
		
		/**
		@brief 
		Affecte l'entrée 3 du module chargé\n
		Si toutes les entrées sont chargé le module est exécuté (QCVModuleInterface::process()) et un signal est émit en sortie.		
		*/	
		void input3(cv::Mat & m);

		/**
		@brief
		Recharge le module
		*/  
		void reload();

		/**
		@brief Gestion automatique de la fonction process par le handler
		*/
		void setAutoProcess(bool autop);

  signals:
		/**
		@brief résultat de la fonction QCVModuleInterface::process() du module		
		*/
		void output(cv::Mat & m);
		
		/**
		@brief envoie un signal de fermeture pour gerer la desalocation du module dan la liste des fenetres
		*/
		void isClosing(QCVModuleHandler * pthis);
		
		/**
		@brief demande le rafraichissement de la vue
		*/
		void move();

  private:
  
		QPluginLoader * pluginLoader;
		bool loadModule(QString filename);

		bool isTokenFull();
		void clearToken();
		bool token[4];
		bool autoProcess;
		bool loaded;
		
		QString filename;
		QCVModuleInterface * moduleInterface;

	protected:
		void moveEvent(QMoveEvent * e);
		//void focusInEvent(QFocusEvent * e);
		//void focusOutEvent(QFocusEvent * e);
		//void resizeEvent(QResizeEvent * e);
};

typedef QCVModuleHandler* pQCVModuleHandler;

#endif
